package com.szholly.data.general;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import com.szholly.utils.spring.SpringBeanFactory;
import com.szholly.utils.util.StringUtils;
import com.szholly.data.common.delegate.DataReaderDelegate;

/**
 * 定义ITable基类，实现基于元数据和工作空间的数据操作 2014.6.4
 */
public abstract class TableBase implements ITable {

	private HashMap<String, ArrayList<Field>> rFields;

	/**
	 * 获取表名称
	 */
	@Override
	public String getTableName() {
		return this.getMetadataTableName();
	}

	/**
	 * 获取结构表名称
	 */
	@Override
	public abstract String getMetadataTableName();

	/**
	 * 获取结构表别名
	 */
	@Override
	public abstract String getMetadataTableAliasName();

	/**
	 * 获取表类型
	 */
	@Override
	public TableType getTableType() {
		return TableType.Table;
	}

	/**
	 * 获取字段信息
	 */
	protected abstract HashMap<String, Field> fields();

	private Field[] getFields;

	/**
	 * 获取字段信息
	 */
	@Override
	public Field[] getFields() {
		if (getFields != null) {
			return getFields;
		}

		if (fields() == null) {
			return null;
		}
		getFields = fields().values().toArray(new Field[fields().size()]);
		return getFields;
	}

	/**
	 * 获取分组信息内的上级所有字段
	 */
	@Override
	public Field[] getRPFields(Field fm) {
		String relationGroup = fm.getRelationGroup();
		if (fm == null || StringUtils.IsNullOrSpace(relationGroup)) {
			return null;
		}
		HashMap<String, ArrayList<Field>> rfields = getRelationFields();
		if (rfields.containsKey(relationGroup)) {
			List<Field> fieldList = rfields.get(relationGroup);
			List<Field> resultList = new ArrayList<Field>();
			int curIndex = fm.getRelationIndex();
			for (Field item : fieldList) {
				if (item.getRelationIndex() < curIndex) {
					resultList.add(item);
				} else {
					break;
				}
			}
			return resultList.toArray(new Field[resultList.size()]);
		} else {
			return null;
		}
	}

	/**
	 * 获取分组字段集
	 * 
	 * @return
	 */
	private HashMap<String, ArrayList<Field>> getRelationFields() {
		if (rFields != null) {
			return rFields;
		}
		rFields = new HashMap<String, ArrayList<Field>>();
		Field[] fields = getFields();
		for (Field item : fields) {
			String relationGroup = item.getRelationGroup();
			if (StringUtils.IsNullOrSpace(relationGroup)) {
				continue;
			}
			ArrayList<Field> rFieldList = null;
			if (rFields.containsKey(relationGroup)) {
				rFieldList = rFields.get(relationGroup);
			} else {
				rFieldList = new ArrayList<Field>();
				rFields.put(relationGroup, rFieldList);
			}
			rFieldList.add(item);
		}
		Set<String> keys = rFields.keySet();
		for (String key : keys) {
			ArrayList<Field> rFieldList = rFields.get(key);
			Collections.sort(rFieldList, comparator);
		}
		return rFields;
	}

	Comparator<Field> comparator = new Comparator<Field>() {
		public int compare(Field s1, Field s2) {
			return s1.getRelationIndex() - s2.getRelationIndex();
		}
	};

	/**
	 * 获取字段总数
	 */
	@Override
	public int getFieldCount() {
		return fields().values().size();
	}

	private Field[] keyNoAutoFields;

	/**
	 * 获取主键，非自动填充
	 */
	@Override
	public Field[] getKeyNoAutoFields() {
		if (keyNoAutoFields != null) {
			return keyNoAutoFields;
		}

		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (item.getIsKey() && !item.getIsAuto())
				keys.add(item);
		}
		keyNoAutoFields = keys.toArray(new Field[keys.size()]);
		return keyNoAutoFields;
	}

	private Field[] uniqueFields;

	/**
	 * 获取唯一值，非key和auto
	 */
	@Override
	public Field[] getUniqueFields() {
		if (uniqueFields != null) {
			return uniqueFields;
		}

		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (!StringUtils.IsNullOrSpace(item.getUniqueGroup()))
				keys.add(item);
		}
		uniqueFields = keys.toArray(new Field[keys.size()]);
		return uniqueFields;
	}

	private HashMap<String, List<Field>> uniqueFieldDic;

	/**
	 * 获取唯一值分组缓存
	 * 
	 * @return
	 */
	@Override
	public HashMap<String, List<Field>> getUniqueFieldMap() {
		if (uniqueFieldDic != null) {
			return uniqueFieldDic;
		}
		uniqueFieldDic = new HashMap<String, List<Field>>();
		for (Field item : getUniqueFields()) {
			String key = item.getUniqueGroup().trim().toUpperCase();
			if (uniqueFieldDic.containsKey(key)) {
				uniqueFieldDic.get(key).add(item);
				uniqueFieldDic.put(key, uniqueFieldDic.get(key));
			} else {
				List<Field> items = new ArrayList<Field>();
				items.add(item);
				uniqueFieldDic.put(key, items);
			}
		}
		return uniqueFieldDic;
	}

	private Field[] autoFields;

	/**
	 * 获取自动增值字段
	 */
	@Override
	public Field[] getAutoFields() {
		if (autoFields != null) {
			return autoFields;
		}
		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (item.getIsAuto())
				keys.add(item);
		}
		autoFields = keys.toArray(new Field[keys.size()]);
		return autoFields;
	}

	private Field[] codeRuleFields;

	/**
	 * 获取需要编码规则的字段
	 */
	@Override
	public Field[] getCodeRuleFields() {
		if (codeRuleFields != null) {
			return codeRuleFields;
		}
		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();

		for (Field item : fields) {
			if (!StringUtils.IsNullOrEmpty(item.getCodeRuleExp())) {
				keys.add(item);
			}
		}
		codeRuleFields = keys.toArray(new Field[keys.size()]);
		return codeRuleFields;
	}

	private String onlyCanShowSelectedFields;
	private String allSelectedFields;

	/**
	 * 获取查询字符串
	 */
	@Override
	public String getSelectFields(boolean onlyCanShow) {
		if (onlyCanShow) {
			if (onlyCanShowSelectedFields != null) {
				return onlyCanShowSelectedFields;
			}
		} else {
			if (allSelectedFields != null) {
				return allSelectedFields;
			}
		}

		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		String selectFields = "";
		for (Field item : fields) {
			if (onlyCanShow) {
				if (item.getCanShow()) {
					selectFields += "[" + item.getFieldName() + "],";
				}
			} else {
				selectFields += "[" + item.getFieldName() + "],";
			}
		}
		if (!StringUtils.IsNullOrSpace(selectFields))
			selectFields = selectFields.substring(0, selectFields.length() - 1);

		if (onlyCanShow) {
			onlyCanShowSelectedFields = selectFields;
		} else {
			allSelectedFields = selectFields;
		}
		return selectFields;
	}

	/**
	 * 根据字段名获取字段信息 fieldName 字段名
	 */
	@Override
	public Field getField(String fieldName) {
		if (fields() == null)
			return null;

		fieldName = fieldName.toUpperCase().trim();
		if (fields().containsKey(fieldName))
			return fields().get(fieldName);
		else
			return null;
	}

	private Field[] keyFields;

	/**
	 * 获取主键
	 */
	@Override
	public Field[] getKeyFields() {
		if (keyFields != null) {
			return keyFields;
		}
		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (item.getIsKey())
				keys.add(item);
		}
		keyFields = keys.toArray(new Field[keys.size()]);
		return keyFields;
	}

	private Field[] keyAndAutoFields;

	/**
	 * 获取主键
	 */
	@Override
	public Field[] getKeyAndAutoFields() {
		if (keyAndAutoFields != null) {
			return keyAndAutoFields;
		}
		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (item.getIsKey() || item.getIsAuto())
				keys.add(item);
		}
		keyAndAutoFields = keys.toArray(new Field[keys.size()]);
		return keyAndAutoFields;
	}

	/**
	 * 是否是代码表
	 */
	@Override
	public boolean getIsCodeTable() {
		return false;
	}

	/**
	 * 是否为树型表
	 */
	@Override
	public boolean getIsTreeTable() {
		return false;
	}

	/**
	 * 获取或设置数据字典表代码字段名
	 */
	@Override
	public String getCodeFieldName() {
		return null;
	}

	/**
	 * 获取或设置数据字典表值字段名
	 */
	@Override
	public String getCaptionFieldName() {
		return null;
	}

	/**
	 * 获取或设置树形表ID字段名
	 */
	@Override
	public String getIDFieldName() {
		return null;
	}

	/**
	 * 获取或设置树形表PID字段名
	 */
	@Override
	public String getPIDFieldName() {
		return null;
	}

	/**
	 * 表关系
	 */
	@Override
	public RelationNode getRelation() {
		return null;
	}

	/**
	 * 空间参考信息
	 */
	@Override
	public String getSpatialReference() {
		return null;
	}

	/**
	 * 获取是否可管理的代码表
	 */
	@Override
	public boolean getIsManageCodeTable() {
		return false;
	}

	/**
	 * 获取简单分组
	 */
	@Override
	public abstract String getTableGroup();

	/**
	 * 获取排序字段名
	 */
	@Override
	public String getOrderFieldName() {
		return null;
	}

	/**
	 * 获取是否使用字段名
	 */
	@Override
	public String getIsUsedFieldName() {
		return null;
	}

	/**
	 * 获取是否可编辑字段名
	 */
	@Override
	public String getIsEditFieldName() {
		return null;
	}
	
	/**
	 * 获取是否可编辑字段名
	 */
	@Override
	public String getUnitFieldName() {
		return null;
	}

	/**
	 * 获取级别字段名
	 */
	@Override
	public String getLevelFieldName() {
		return null;
	}
	
	/**
	 * 获取是否为叶子节点字段名
	 */
	@Override
	public String getIsChildFieldName() {
		return null;
	}

	/**
	 * 获取字典阈名称
	 */
	@Override
	public String getDomainFieldName() {
		return null;
	}

	/**
	 * 获取GUID字段名称
	 */
	@Override
	public String getGUIDFieldName() {
		return RowBase.FIELD_GUID;
	}

	/**
	 * 获取版本字段名称
	 */
	@Override
	public String getVersionFieldName() {
		return "";
	}

	/**
	 * 获取企业名称字段
	 */
	@Override
	public String getCompanyName() {
		return RowBase.FIELD_COMPANY;
	}
	
	/**
	 * 获取系统名称字段
	 */
	@Override
	public String getSystemName() {
		return RowBase.FIELD_SYSTEMNAME;
	}

	/**
	 * 获取当前表空间
	 */
	@Override
	public IWorkspace getWorkspace() {
		IWorkspaceFactory workspaceFactory = (IWorkspaceFactory) SpringBeanFactory
				.getBean("WorkspaceFactory");
		IWorkspace pWorkspace = workspaceFactory.openWorkspace();
		tableInit(pWorkspace);
		return pWorkspace;
	}

	private boolean tableIsInit = false;

	private void tableInit(IWorkspace pWorkspace) {
		if (tableIsInit) {
			return;
		}
		if (!pWorkspace.objectExist(this.getTableName())) {
			pWorkspace.createTable(this, getTableName());
		}
		tableIsInit = true;
	}

	/**
	 * 获取当前元数据表空间
	 */
	@Override
	public ITableFactory getTableFactory() {
		ITableFactory tableFactory = (ITableFactory) SpringBeanFactory
				.getBean("TableFactory");
		return tableFactory;
	}

	/**
	 * 开始编辑
	 */
	@Override
	public void startEditing() {
		getWorkspace().startEditing();
	}

	/**
	 * 停止编辑
	 */
	@Override
	public void stopEditing(boolean saveEdits) {
		getWorkspace().stopEditing(saveEdits);
	}

	/**
	 * 当前是否处于编辑状态
	 */
	@Override
	public boolean getIsBeingEdited() {
		return getWorkspace().isBeingEdited();
	}

	/**
	 * 返回DataReader数据
	 * 
	 * @param queryFilter
	 * @param dataDelegate
	 */
	@Override
	public <T extends RowBase> void getDataReader(Class<T> c, IQueryFilter queryFilter,
			DataReaderDelegate dataDelegate) {
		if (dataDelegate == null)
			return;
		getWorkspace().getDataReader(c, this, queryFilter,
				dataDelegate);
	}

	/**
	 * 返回DataReader数据
	 * 
	 * @param queryFilter
	 * @param dataDelegate
	 */
	@Override
	public <T extends RowBase> void getDataReader(Class<T> c, IQueryMap queryFilter,
			DataReaderDelegate dataDelegate) {
		if (dataDelegate == null)
			return;
		getWorkspace().getDataReader(c, this, queryFilter,
				dataDelegate);
	}

	/**
	 * 返回DataReader数据
	 * 
	 * @param queryFilter
	 * @param dataDelegate
	 */
	@Override
	public <T extends RowBase> void getDataReader(Class<T> c, RowBase queryFilter,
			DataReaderDelegate dataDelegate) {
		if (dataDelegate == null)
			return;
		getWorkspace().getDataReader(c, this, queryFilter,
				dataDelegate);
	}

	/**
	 * 执行SQL语句返回查询结果object
	 * 
	 * @param queryFilter
	 * @return
	 */
	@Override
	public Object getExecuteScalar(IQueryFilter queryFilter) {
		return getWorkspace().getExecuteScalar(this, queryFilter);
	}

	/**
	 * 执行SQL语句返回查询结果object
	 * 
	 * @param queryFilter
	 * @return
	 */
	@Override
	public Object getExecuteScalar(IQueryMap queryFilter) {
		return getWorkspace().getExecuteScalar(this,
				queryFilter);
	}

	/**
	 * 执行SQL语句返回查询结果object
	 * 
	 * @param queryFilter
	 * @return
	 */
	@Override
	public Object getExecuteScalar(RowBase queryFilter) {
		return getWorkspace().getExecuteScalar(this,
				queryFilter);
	}

	/**
	 * 将数据绑定到自定义数据类型上
	 * 
	 * @param queryFilter
	 * @return
	 */
	@Override
	public <T extends RowBase> T getEntity(Class<T> c, IQueryFilter queryFilter) {
		return getWorkspace().getEntity(c, this,
				queryFilter);
	}

	/**
	 * 将数据绑定到自定义数据类型上
	 * 
	 * @param queryFilter
	 * @return
	 */
	@Override
	public <T extends RowBase> T getEntity(Class<T> c, IQueryMap queryFilter) {
		return getWorkspace().getEntity(c, this,
				queryFilter);
	}

	/**
	 * 将数据绑定到自定义数据类型上
	 * 
	 * @param queryFilter
	 * @return
	 */
	@Override
	public <T extends RowBase> T getEntity(Class<T> c, RowBase queryFilter) {
		return getWorkspace().getEntity(c, this,
				queryFilter);
	}

	/**
	 * 将数据绑定到自定义数据类型上
	 * 
	 * @param queryFilter
	 * @return
	 */
	@Override
	public <T extends RowBase> List<T> getEntityList(Class<T> c, IQueryFilter queryFilter) {
		return getWorkspace().getEntityList(c, this,
				queryFilter);
	}

	/**
	 * 将数据绑定到自定义数据类型上
	 * 
	 * @param queryFilter
	 * @return
	 */
	@Override
	public <T extends RowBase> List<T> getEntityList(Class<T> c, IQueryMap queryFilter) {
		return getWorkspace().getEntityList(c, this,
				queryFilter);
	}

	/**
	 * 将数据绑定到自定义数据类型上
	 * 
	 * @param queryFilter
	 * @return
	 */
	@Override
	public <T extends RowBase> List<T> getEntityList(Class<T> c, RowBase queryFilter) {
		return getWorkspace().getEntityList(c, this,
				queryFilter);
	}

	/**
	 * 分页查询
	 * 
	 * @param queryFilter
	 * @param pageInfo
	 * @return
	 */
	@Override
	public <T extends RowBase> List<T> pageSelect(Class<T> c, IQueryFilter queryFilter,
			PageInfo pageInfo) {
		return getWorkspace().getEntityList(c, this,
				queryFilter);
	}

	/**
	 * 分页查询
	 * 
	 * @param queryFilter
	 * @param pageInfo
	 * @return
	 */
	@Override
	public <T extends RowBase> List<T> pageSelect(Class<T> c, IQueryMap queryFilter,
			PageInfo pageInfo) {
		return getWorkspace().pageSelect(c, this,
				queryFilter, pageInfo);
	}

	/**
	 * 分页查询
	 * 
	 * @param queryFilter
	 * @param pageInfo
	 * @return
	 */
	@Override
	public <T extends RowBase> List<T> pageSelect(Class<T> c, RowBase queryFilter,
			PageInfo pageInfo) {
		return getWorkspace().pageSelect(c, this,
				queryFilter, pageInfo);
	}

	/**
	 * 获取某列的最大值
	 * 
	 * @param fieldName
	 * @param otherCondition
	 * @param paras
	 * @return
	 */
	@Override
	public long getSpecFieldMaxValue(String fieldName, String otherCondition,
			GlobalParameter[] paras) {
		return getWorkspace().getSpecFieldMaxValue(this,
				fieldName, otherCondition, paras);
	}

	/**
	 * 获取某列的最小值
	 * 
	 * @param fieldName
	 * @param otherCondition
	 * @param paras
	 * @return
	 */
	@Override
	public long getSpecFieldMinValue(String fieldName, String otherCondition,
			GlobalParameter[] paras) {
		return getWorkspace().getSpecFieldMinValue(this,
				fieldName, otherCondition, paras);
	}

	/**
	 * 获取下一个要素，如果没有返回null
	 * 
	 * @param t
	 * @param byFieldName
	 * @param whereString
	 * @param orderByType
	 * @param addCaptionField
	 * @return
	 */
	@Override
	public <T extends RowBase> T getNextEntity(Class<T> c, RowBase t, String byFieldName,
			String whereString, OrderByType orderByType, boolean addCaptionField) {
		return getWorkspace().getNextEntity(c, this, t,
				byFieldName, whereString, orderByType, addCaptionField);
	}

	/**
	 * 获取上一个要素，如果没有返回null
	 * 
	 * @param t
	 * @param byFieldName
	 * @param whereString
	 * @param orderByType
	 * @param addCaptionField
	 * @return
	 */
	@Override
	public <T extends RowBase> T getPerEntity(Class<T> c, RowBase t, String byFieldName,
			String whereString, OrderByType orderByType, boolean addCaptionField) {
		return getWorkspace().getPerEntity(c, this, t,
				byFieldName, whereString, orderByType, addCaptionField);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public void save(RowBase entity) {
		getWorkspace().save(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public <T extends RowBase> void save(List<T> entity) {
		getWorkspace().save(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public void insert(RowBase entity) {
		getWorkspace().insert(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public <T extends RowBase> void insert(List<T> entity) {
		getWorkspace().insert(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public void update(RowBase entity) {
		getWorkspace().update(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public <T extends RowBase> void update(List<T> entity) {
		getWorkspace().update(this, entity);
	}

	/**
	 * 更新数据
	 * 
	 * @param updateFilter
	 */
	@Override
	public void update(IUpdateFilter updateFilter) {
		getWorkspace().update(this, updateFilter);
	}

	/**
	 * 更新数据
	 * 
	 * @param updateFilter
	 */
	@Override
	public void update(IUpdateMap updateFilter) {
		getWorkspace().update(this, updateFilter);
	}

	/**
	 * 删除表记录
	 * 
	 * @param queryFilter
	 */
	@Override
	public void delete(IQueryFilter queryFilter) {
		getWorkspace().delete(this, queryFilter);
	}

	/**
	 * 删除表记录
	 * 
	 * @param queryFilter
	 */
	@Override
	public void delete(IQueryMap queryFilter) {
		getWorkspace().delete(this, queryFilter);
	}

	/**
	 * 删除记录行
	 * 
	 * @param row
	 */
	@Override
	public void delete(RowBase row) {
		getWorkspace().delete(this, row);
	}

	/**
	 * 添加字段
	 */
	public void addField(Field field) {
		if (field != null && !StringUtils.IsNullOrSpace(field.getFieldName())) {
			if (fields().containsKey(field.getFieldName().toUpperCase().trim())) {
				fields().put(field.getFieldName().toUpperCase().trim(), field);
				this.getWorkspace().updateTable(this, this.getTableName());
			}
		}
	}

	/**
	 * 移除字段
	 */
	public void removeField(Field field) {
		if (field != null && !StringUtils.IsNullOrSpace(field.getFieldName())) {
			if (fields().containsKey(field.getFieldName().toUpperCase().trim())) {
				fields().remove(field.getFieldName().toUpperCase().trim());
				this.getWorkspace().updateTable(this, this.getTableName());
			}
		}
	}

	/**
	 * 更新字段
	 */
	public void updateField(Field field) {
		if (field != null && !StringUtils.IsNullOrSpace(field.getFieldName())) {
			if (fields().containsKey(field.getFieldName().toUpperCase().trim())) {
				fields().put(field.getFieldName().toUpperCase().trim(), field);
				this.getWorkspace().updateTable(this, this.getTableName());
			}
		}
	}
}